import * as fs from 'fs';
import * as path from 'path';
import { JavaParser } from '../utils/JavaParser.js';

export interface ServiceInterfaceResult {
  success: boolean;
  message: string;
  generatedFiles: Array<{
    filePath: string;
    description: string;
  }>;
  interfaceMethods?: string[];
  errors?: string[];
}

export interface ServiceMethod {
  name: string;
  returnType: string;
  parameters: Array<{
    type: string;
    name: string;
  }>;
  signature: string;
  javadoc?: string;
  annotations: string[];
  isPublic: boolean;
}

/**
 * Service接口生成器 - 从Service类生成Interface + Implementation模式
 */
export class ServiceInterfaceGenerator {

  async generateInterface(filePath: string, interfaceName?: string, implName?: string): Promise<ServiceInterfaceResult> {
    const result: ServiceInterfaceResult = {
      success: false,
      message: '',
      generatedFiles: [],
      interfaceMethods: [],
      errors: []
    };

    try {
      console.error(`[ServiceInterfaceGenerator] 开始生成Service接口: ${filePath}`);
      
      const fileContent = fs.readFileSync(filePath, 'utf-8');
      const originalClassName = this.extractClassName(fileContent);
      
      if (!originalClassName) {
        result.errors?.push('无法识别原始类名');
        result.message = '无法识别原始类名';
        return result;
      }

      console.error(`[ServiceInterfaceGenerator] 识别到原始类名: ${originalClassName}`);

      // 确定接口名和实现类名
      const finalInterfaceName = interfaceName || this.generateInterfaceName(originalClassName);
      const finalImplName = implName || this.generateImplName(originalClassName);

      console.error(`[ServiceInterfaceGenerator] 接口名: ${finalInterfaceName}, 实现类名: ${finalImplName}`);

      // 解析Service结构
      const serviceStructure = this.analyzeServiceStructure(fileContent);
      console.error(`[ServiceInterfaceGenerator] 找到 ${serviceStructure.publicMethods.length} 个公共方法`);

      if (serviceStructure.publicMethods.length === 0) {
        result.errors?.push('没有找到可提取的公共方法');
        result.message = '没有找到可提取的公共方法';
        return result;
      }

      const baseDir = path.dirname(filePath);
      const packageName = this.extractPackageName(fileContent);
      const originalImports = this.extractImports(fileContent);

      // 生成接口文件
      const interfaceContent = this.generateInterfaceFile(
        finalInterfaceName,
        packageName,
        serviceStructure.publicMethods,
        originalImports
      );

      const interfaceFilePath = path.join(baseDir, `${finalInterfaceName}.java`);
      fs.writeFileSync(interfaceFilePath, interfaceContent, 'utf-8');

      result.generatedFiles.push({
        filePath: interfaceFilePath,
        description: `Service接口 - 包含${serviceStructure.publicMethods.length}个公共方法`
      });

      console.error(`[ServiceInterfaceGenerator] 生成接口文件: ${interfaceFilePath}`);

      // 生成实现类文件
      const implContent = this.generateImplementationFile(
        finalImplName,
        finalInterfaceName,
        packageName,
        fileContent,
        serviceStructure.publicMethods,
        originalImports
      );

      const implFilePath = path.join(baseDir, `${finalImplName}.java`);
      fs.writeFileSync(implFilePath, implContent, 'utf-8');

      result.generatedFiles.push({
        filePath: implFilePath,
        description: `Service实现类 - 实现${finalInterfaceName}接口`
      });

      console.error(`[ServiceInterfaceGenerator] 生成实现类文件: ${implFilePath}`);

      // 设置结果
      result.success = true;
      result.message = `成功生成 ${finalInterfaceName} 接口和 ${finalImplName} 实现类`;
      result.interfaceMethods = serviceStructure.publicMethods.map(m => m.signature);

    } catch (error) {
      result.errors?.push(`生成Service接口失败: ${error}`);
      result.message = `生成Service接口失败: ${error}`;
      console.error(`[ServiceInterfaceGenerator] 错误:`, error);
    }

    return result;
  }

  private extractClassName(content: string): string | null {
    const match = content.match(/public\s+class\s+(\w+)/);
    return match ? match[1] : null;
  }

  private generateInterfaceName(originalClassName: string): string {
    // 如果类名以Service结尾，去掉Service；否则加Interface
    if (originalClassName.endsWith('Service')) {
      const baseName = originalClassName.slice(0, -7); // 去掉"Service"
      return baseName + 'Service'; // 保持Service后缀，但这是接口
    }
    return originalClassName + 'Interface';
  }

  private generateImplName(originalClassName: string): string {
    // 如果类名以Service结尾，改为ServiceImpl；否则加Impl
    if (originalClassName.endsWith('Service')) {
      const baseName = originalClassName.slice(0, -7); // 去掉"Service"
      return baseName + 'ServiceImpl';
    }
    return originalClassName + 'Impl';
  }

  private extractPackageName(content: string): string {
    const match = content.match(/package\s+([^;]+);/);
    return match ? match[1] : 'com.example.service';
  }

  private extractImports(content: string): string[] {
    const imports: string[] = [];
    const lines = content.split('\n');
    
    for (const line of lines) {
      const trimmed = line.trim();
      if (trimmed.startsWith('import ') && trimmed.endsWith(';')) {
        imports.push(trimmed);
      }
    }
    
    return imports;
  }

  private analyzeServiceStructure(content: string): {
    publicMethods: ServiceMethod[],
    privateMethods: ServiceMethod[],
    fields: string[],
    classAnnotations: string[]
  } {
    const publicMethods: ServiceMethod[] = [];
    const privateMethods: ServiceMethod[] = [];
    const fields: string[] = [];
    const classAnnotations: string[] = [];
    
    const lines = content.split('\n');
    
    // 提取类注解
    let foundClass = false;
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i].trim();
      if (line.startsWith('@') && !foundClass) {
        classAnnotations.push(line);
      } else if (line.includes('public class ')) {
        foundClass = true;
        break;
      }
    }
    
    // 提取字段和方法
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      
      // 检测字段
      if (this.isFieldDefinition(line)) {
        fields.push(line.trim());
      }
      
      // 检测方法定义
      if (this.isMethodDefinition(line)) {
        const methodName = this.extractMethodName(line);
        if (methodName) {
          const methodInfo = JavaParser.findMethodBounds(content, methodName);
          if (methodInfo) {
            const methodContent = lines.slice(methodInfo.startLine - 1, methodInfo.endLine).join('\n');
            const method = this.parseMethodDetails(methodContent, lines, methodInfo.startLine - 1);
            
            if (method.isPublic) {
              publicMethods.push(method);
            } else {
              privateMethods.push(method);
            }
          }
        }
      }
    }
    
    return { publicMethods, privateMethods, fields, classAnnotations };
  }

  private isFieldDefinition(line: string): boolean {
    const trimmed = line.trim();
    return trimmed.startsWith('@Autowired') ||
           (trimmed.includes('private ') && trimmed.endsWith(';') && !trimmed.includes('(')) ||
           (trimmed.includes('public ') && trimmed.endsWith(';') && !trimmed.includes('(')) ||
           (trimmed.includes('protected ') && trimmed.endsWith(';') && !trimmed.includes('('));
  }

  private isMethodDefinition(line: string): boolean {
    const trimmed = line.trim();
    return (trimmed.includes('public ') || trimmed.includes('private ') || trimmed.includes('protected ')) &&
           trimmed.includes('(') && 
           (trimmed.includes('{') || trimmed.endsWith(')'));
  }

  private extractMethodName(line: string): string | null {
    const match = line.match(/\b(\w+)\s*\(/);
    return match ? match[1] : null;
  }

  private parseMethodDetails(methodContent: string, allLines: string[], methodStartIndex: number): ServiceMethod {
    const lines = methodContent.split('\n');
    const signatureLine = lines[0];
    
    const method: ServiceMethod = {
      name: '',
      returnType: 'void',
      parameters: [],
      signature: '',
      annotations: [],
      isPublic: false
    };
    
    // 提取方法注解
    for (let i = methodStartIndex - 1; i >= 0; i--) {
      const line = allLines[i].trim();
      if (line.startsWith('@')) {
        method.annotations.unshift(line);
      } else if (line !== '' && !line.startsWith('//') && !line.startsWith('*')) {
        break;
      }
    }
    
    // 提取Javadoc
    for (let i = methodStartIndex - 1; i >= 0; i--) {
      const line = allLines[i].trim();
      if (line.startsWith('/**')) {
        const javadocLines: string[] = [];
        for (let j = i; j < methodStartIndex; j++) {
          const docLine = allLines[j].trim();
          if (docLine.startsWith('*') || docLine.startsWith('/**') || docLine.startsWith('*/')) {
            javadocLines.push(allLines[j]);
          }
        }
        method.javadoc = javadocLines.join('\n');
        break;
      }
    }
    
    // 解析方法签名
    method.isPublic = signatureLine.includes('public ');
    
    // 提取方法名
    const nameMatch = signatureLine.match(/\b(\w+)\s*\(/);
    if (nameMatch) {
      method.name = nameMatch[1];
    }
    
    // 提取返回类型
    const returnTypeMatch = signatureLine.match(/(?:public|private|protected)\s+(?:static\s+)?(?:final\s+)?(\w+(?:<[^>]+>)?(?:\[\])?)\s+\w+\s*\(/);
    if (returnTypeMatch) {
      method.returnType = returnTypeMatch[1];
    }
    
    // 提取参数
    const paramMatch = signatureLine.match(/\(([^)]*)\)/);
    if (paramMatch && paramMatch[1].trim()) {
      const paramStr = paramMatch[1];
      const params = paramStr.split(',');
      
      for (const param of params) {
        const cleanParam = param.trim();
        const parts = cleanParam.split(/\s+/);
        if (parts.length >= 2) {
          method.parameters.push({
            type: parts[parts.length - 2],
            name: parts[parts.length - 1]
          });
        }
      }
    }
    
    // 生成方法签名
    const paramString = method.parameters.map(p => `${p.type} ${p.name}`).join(', ');
    method.signature = `${method.returnType} ${method.name}(${paramString})`;
    
    return method;
  }

  private generateInterfaceFile(
    interfaceName: string,
    packageName: string,
    methods: ServiceMethod[],
    originalImports: string[]
  ): string {
    const lines: string[] = [];
    
    // Package声明
    lines.push(`package ${packageName};`);
    lines.push('');
    
    // 基础imports
    const requiredImports = this.getRequiredImportsForInterface(methods);
    const filteredImports = originalImports.filter(imp => 
      requiredImports.some(req => imp.includes(req)) && 
      !imp.includes('org.springframework.stereotype.Service') &&
      !imp.includes('org.springframework.beans.factory.annotation.Autowired')
    );
    
    filteredImports.forEach(imp => lines.push(imp));
    lines.push('');
    
    // 接口注释
    lines.push('/**');
    lines.push(` * ${interfaceName} - Service接口`);
    lines.push(' * 定义业务服务的公共契约');
    lines.push(' */');
    lines.push(`public interface ${interfaceName} {`);
    lines.push('');
    
    // 接口方法
    methods.forEach(method => {
      // 添加Javadoc
      if (method.javadoc) {
        const javadocLines = method.javadoc.split('\n');
        javadocLines.forEach(line => {
          lines.push(`    ${line}`);
        });
      } else {
        lines.push('    /**');
        lines.push(`     * ${method.name}`);
        method.parameters.forEach(param => {
          lines.push(`     * @param ${param.name} ${param.name}`);
        });
        if (method.returnType !== 'void') {
          lines.push(`     * @return ${method.returnType}`);
        }
        lines.push('     */');
      }
      
      // 添加方法声明
      const paramString = method.parameters.map(p => `${p.type} ${p.name}`).join(', ');
      lines.push(`    ${method.returnType} ${method.name}(${paramString});`);
      lines.push('');
    });
    
    lines.push('}');
    
    return lines.join('\n');
  }

  private generateImplementationFile(
    implName: string,
    interfaceName: string,
    packageName: string,
    originalContent: string,
    methods: ServiceMethod[],
    originalImports: string[]
  ): string {
    const lines: string[] = [];
    
    // Package声明
    lines.push(`package ${packageName};`);
    lines.push('');
    
    // Imports
    const requiredImports = this.getRequiredImportsForImpl(methods);
    const filteredImports = originalImports.filter(imp => 
      requiredImports.some(req => imp.includes(req))
    );
    
    // 确保有Service注解的import
    if (!filteredImports.some(imp => imp.includes('org.springframework.stereotype.Service'))) {
      lines.push('import org.springframework.stereotype.Service;');
    }
    
    filteredImports.forEach(imp => lines.push(imp));
    lines.push('');
    
    // 实现类注释
    lines.push('/**');
    lines.push(` * ${implName} - ${interfaceName}接口实现`);
    lines.push(' * 具体的业务逻辑实现');
    lines.push(' */');
    lines.push('@Service');
    lines.push(`public class ${implName} implements ${interfaceName} {`);
    lines.push('');
    
    // 从原始文件中提取字段、私有方法等
    const originalLines = originalContent.split('\n');
    let inClass = false;
    let braceCount = 0;
    
    for (let i = 0; i < originalLines.length; i++) {
      const line = originalLines[i];
      
      if (line.includes('public class ')) {
        inClass = true;
        continue;
      }
      
      if (!inClass) continue;
      
      // 计算大括号
      for (const char of line) {
        if (char === '{') braceCount++;
        if (char === '}') braceCount--;
      }
      
      // 在类的第一层级复制内容
      if (braceCount === 1) {
        const trimmed = line.trim();
        
        // 复制字段
        if (this.isFieldDefinition(line)) {
          lines.push(line);
          continue;
        }
        
        // 跳过公共方法声明（因为会从接口实现）
        if (this.isMethodDefinition(line) && line.includes('public ')) {
          const methodName = this.extractMethodName(line);
          if (methodName && methods.some(m => m.name === methodName)) {
            // 找到完整的方法并复制
            const methodInfo = JavaParser.findMethodBounds(originalContent, methodName);
            if (methodInfo) {
              // 添加@Override注解
              lines.push('    @Override');
              
              // 复制完整方法
              for (let j = methodInfo.startLine - 1; j < methodInfo.endLine; j++) {
                lines.push(originalLines[j]);
              }
              lines.push('');
              
              // 跳过原方法行
              i = methodInfo.endLine - 1;
              continue;
            }
          }
        }
        
        // 复制私有方法和其他内容
        if (this.isMethodDefinition(line) && line.includes('private ')) {
          const methodName = this.extractMethodName(line);
          if (methodName) {
            const methodInfo = JavaParser.findMethodBounds(originalContent, methodName);
            if (methodInfo) {
              // 复制完整的私有方法
              for (let j = methodInfo.startLine - 1; j < methodInfo.endLine; j++) {
                lines.push(originalLines[j]);
              }
              lines.push('');
              
              // 跳过原方法行
              i = methodInfo.endLine - 1;
              continue;
            }
          }
        }
      }
      
      if (braceCount === 0 && inClass) {
        break; // 类结束
      }
    }
    
    lines.push('}');
    
    return lines.join('\n');
  }

  private getRequiredImportsForInterface(methods: ServiceMethod[]): string[] {
    const imports = new Set<string>();
    
    methods.forEach(method => {
      // 检查返回类型和参数类型需要的imports
      const allTypes = [method.returnType, ...method.parameters.map(p => p.type)];
      
      allTypes.forEach(type => {
        if (type.includes('List') || type.includes('Map') || type.includes('Set')) {
          imports.add('java.util');
        }
        if (type.includes('LocalDateTime')) {
          imports.add('java.time.LocalDateTime');
        }
        if (type.includes('BigDecimal')) {
          imports.add('java.math.BigDecimal');
        }
      });
    });
    
    return Array.from(imports);
  }

  private getRequiredImportsForImpl(methods: ServiceMethod[]): string[] {
    const imports = new Set<string>();
    
    // 基础Spring imports
    imports.add('org.springframework.stereotype.Service');
    imports.add('org.springframework.beans.factory.annotation.Autowired');
    imports.add('org.springframework.transaction.annotation.Transactional');
    
    // 方法相关imports
    methods.forEach(method => {
      const allTypes = [method.returnType, ...method.parameters.map(p => p.type)];
      
      allTypes.forEach(type => {
        if (type.includes('List') || type.includes('Map') || type.includes('Set')) {
          imports.add('java.util');
        }
        if (type.includes('LocalDateTime')) {
          imports.add('java.time.LocalDateTime');
        }
        if (type.includes('BigDecimal')) {
          imports.add('java.math.BigDecimal');
        }
      });
    });
    
    return Array.from(imports);
  }
}